

export type Method = "get" | "GET" | "delete" | "DELETE" | "put" | "PUT" | "POST" | "post" | "HEAD" | "head" | "options" | "OPTIONS"


export interface AxiosRequestConfig{
    url?: string
    method?: Method
    data?: any
    params?: any
    headers?: any
    responseType?: XMLHttpRequestResponseType
    timeout?: number
    transformRequest?: AxiosTransformer| AxiosTransformer[]
    transformResponse?: AxiosTransformer| AxiosTransformer[]
    CancelToken?: CancelToken
    withCredentials?: boolean
    xsrfCookieName?: string
    xsrfHeaderName?: string
    onDownloadProgress?: (e: ProgressEvent)=>void
    onUploadProgress?: (e: ProgressEvent)=>void
    auth?: AxiosBasicCerdentials
    validateStatus?: (status: number)=> boolean
    paramsSerialzer?: (params: any)=>string
    baseURL?: string

    [propName:string]: any
}

export interface  AxiosResponse<T=any>{
    data?: T
    status: number
    statusText: string
    headers: any
    config: AxiosRequestConfig
    request: any
}

export interface AxiosPromise<T=any> extends  Promise<AxiosResponse<T>>{

}

export  interface Axios{
    defautls: AxiosRequestConfig
    interceptors: {
        request: AxiosInterectorManager<AxiosRequestConfig>
        response: AxiosInterectorManager<AxiosResponse>
    }
    
    request<T=any>(config: AxiosRequestConfig): AxiosPromise<T>

    get<T=any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
    delete<T=any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
    head<T=any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
    options<T=any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>
    post<T=any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>
    put<T=any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>
    patch<T=any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>

    getUri(config?: AxiosRequestConfig): string

}

export interface  AxiosInstance extends Axios{
    <T=any>(config: AxiosRequestConfig): AxiosPromise<T>

    <T=any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>

}

export interface AxiosClassStatic{
    new(config: AxiosRequestConfig): AxiosRequestConfig
}

export interface AxiosError extends Error{
    isAxiosError: boolean
    config: AxiosRequestConfig
    code?: string | null
    request?: any
    response?: AxiosResponse
}

export interface AxiosStatic extends AxiosInstance{
    create(config?: AxiosRequestConfig): AxiosInstance

    CancelToken: CancelTokenStatic
    Cancel: CancelStatic
    isCancel: (value: any)=>boolean

    all<T>(promises: Array<T | Promise<T>>): Promise<T[]>

    spread<T, R>(callback: (...args: T[])=>R): (arr: T[]) => R

}

export interface AxiosInterectorManager<T>{
    use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number

    eject(id: number): void

}

export interface ResolvedFn<T>{
    (val: T): T | Promise<T>
}

export interface RejectedFn{
    (error: any): any
}

export interface AxiosTransformer{
    (data: any, headers?: any): any
}

export interface CancelToken{
    promise: Promise<Cancel>
    reason?: Cancel

    throwIfRequest(): void
}

export interface Cancelr{
    (message?: string): void
}

export interface CancelExecutor{
    (cancel: Cancelr): void
}

export interface CancelTokenSource{
    token: CancelToken
    cancel: Cancelr
}

export interface CancelTokenStatic{
    new(executor: CancelExecutor): CancelToken
    source(): CancelTokenSource
}

export interface Cancel{
    message?: string
}

export interface CancelStatic{
    new(message?: string): Cancel
}

export interface AxiosBasicCerdentials{
    username: string
    password: string
}